package rad.framework.mda.jpagen.actions;

import rad.framework.mda.generator.Console;
import rad.framework.mda.generator.util.StereotypeHelper;
import rad.framework.mda.util.ModelUtil;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;

/**
 * @author boudyacho
 * @deprecated
 * 
 */
public class AddTableAndColumnActionExtension extends
		BaseUtiltiyActionExtension {

	protected static final String TABLE = "javax.persistence.Table";

	protected static final String COLUMN = "javax.persistence.Column";

	protected static final String JOIN_COLUMN = "javax.persistence.JoinColumn";

	protected static final String ATTRIBUTE_OVERRIDES = "javax.persistence.AttributeOverrides";

	protected static final String JOIN_TABLE = "javax.persistence.JoinTable";

	public void fillContextMenu(IMenuManager aMenu) {
		getSubMenu(aMenu).add(new CleanupEnumerationsAction());
	}

	protected void execute(Class clazz) {
		if (StereotypeHelper
				.isStereotypeApplied(clazz, StereotypeHelper.ENTITY)) {

			applyTable(clazz);
			Console.getStream().println(
					"Added " + TABLE + " - " + clazz.getQualifiedName());
			EList<NamedElement> list = clazz.getMembers();
			for (NamedElement namedElement : list) {
				if (namedElement instanceof Property) {
					execute((Property) namedElement);
				}
			}
		}
	}

	protected void execute(Property property) {
		if (ModelUtil.isStereotypeApplied(property,
				"javax.persistence.OneToMany")) {
			return;
		} else if (ModelUtil.isStereotypeApplied(property,
				"javax.persistence.ManyToMany")) {
			if (isSource(property)) {
				applyJoinTable(property);
				Console.getStream().println(
						"Added " + JOIN_TABLE + " - "
								+ property.getQualifiedName());
			}
		} else if (ModelUtil.isStereotypeApplied(property,
				"javax.persistence.ManyToOne")
				|| ModelUtil.isStereotypeApplied(property,
						"javax.persistence.OneToOne")) {
			applyJoinColumn(property);
			Console.getStream().println(
					"Added " + JOIN_COLUMN + " - "
							+ property.getQualifiedName());
		} else if (ModelUtil.isStereotypeApplied(property,
				"javax.persistence.Embedded")) {
			applyAttributeOverrides(property);
			Console.getStream().println(
					"Added " + ATTRIBUTE_OVERRIDES + " - "
							+ property.getQualifiedName());
		} else {
			applyColumn(property);
			Console.getStream().println(
					"Added " + COLUMN + " - " + property.getQualifiedName());
		}
	}

	protected void applyTable(Class element) {
		Stereotype stereotype = (Stereotype) ModelUtil.getProfileElement(
				element, TABLE);
		if (stereotype != null) {
			if (!ModelUtil.isStereotypeApplied(element, TABLE)) {
				element.applyStereotype(stereotype);
			}
			element.setValue(stereotype, "name", NameUtil
					.getAbbreviation(element)
					+ "S");
		}
	}

	private void applyJoinTable(Property element) {
		Stereotype stereotype = (Stereotype) ModelUtil.getProfileElement(
				element, JOIN_TABLE);
		if (stereotype != null) {
			if (ModelUtil.isStereotypeApplied(element, JOIN_TABLE)) {
				element.unapplyStereotype(stereotype);
			}
			EObject application = element.applyStereotype(stereotype);
			element.setValue(stereotype, "name", NameUtil
					.getAbbreviation((NamedElement) element.getOwner())
					+ "_" + NameUtil.getAbbreviation(element.getType()));

			DynamicEObjectImpl joinColumns = createChild(application);
			addChild(application, joinColumns, "joinColumns");
			setAttribute(joinColumns, "name", NameUtil
					.getAbbreviation((NamedElement) element.getOwner())
					+ "_ID");

			DynamicEObjectImpl inverseJoinColumns = createChild(application);
			addChild(application, inverseJoinColumns, "inverseJoinColumns");
			setAttribute(inverseJoinColumns, "name", NameUtil
					.getAbbreviation(element.getType())
					+ "_ID");
		}
	}

	private void applyJoinColumn(Property element) {
		Stereotype stereotype = (Stereotype) ModelUtil.getProfileElement(
				element, JOIN_COLUMN);
		if (stereotype != null) {
			if (!ModelUtil.isStereotypeApplied(element, JOIN_COLUMN)) {
				element.applyStereotype(stereotype);
			}
			element.setValue(stereotype, "name", NameUtil
					.getAbbreviation(element)
					+ "_ID");
		}
	}

	protected void applyColumn(Property element) {
		Stereotype stereotype = (Stereotype) ModelUtil.getProfileElement(
				element, COLUMN);
		if (stereotype != null) {
			if (!ModelUtil.isStereotypeApplied(element, COLUMN)) {
				element.applyStereotype(stereotype);
			}
			if (ModelUtil.isStereotypeApplied(element, "javax.persistence.Id")) {
				element.setValue(stereotype, "name", NameUtil
						.getAbbreviation((NamedElement) element.getOwner())
						+ "_ID");
			} else {
				element.setValue(stereotype, "name", NameUtil
						.getAbbreviation(element));
			}
			if ("String".equals(element.getType().getName())) {
				if (element.getValue(stereotype, "length").equals(
						new Integer(0))) {
					element.setValue(stereotype, "length", 255);
				}
			}
			// TODO other properties
			// length=0
			// unique=false
			// precision=0
			// scale=0
			// nullable=true
			// insertable=true
			// updatable=true

			/*
			 * 
			 * @Column( name="columnName"; (1) boolean unique() default false;
			 * (2) boolean nullable() default true; (3) boolean insertable()
			 * default true; (4) boolean updatable() default true; (5) String
			 * columnDefinition() default ""; (6) String table() default ""; (7)
			 * int length() default 255; (8) int precision() default 0; //
			 * decimal precision (9) int scale() default 0; // decimal scale
			 * 
			 * 
			 */

			// TODO other stereotypes
			// @Id
		}
	}

	private void applyAttributeOverrides(Property element) {
		Stereotype stereotype = (Stereotype) ModelUtil.getProfileElement(
				element, ATTRIBUTE_OVERRIDES);
		if (stereotype != null) {
			if (ModelUtil.isStereotypeApplied(element, ATTRIBUTE_OVERRIDES)) {
				element.unapplyStereotype(stereotype);
			}
			EObject appliedStereotype = element.applyStereotype(stereotype);
			addAttributeOverrides(element, appliedStereotype);
		}
	}

	private void addAttributeOverrides(Property element, EObject stereotype) {
		String prefix = NameUtil.getAbbreviation(element);
		Class type = (Class) element.getType();
		EList<NamedElement> list = type.getMembers();
		for (NamedElement namedElement : list) {
			if (namedElement instanceof Property) {
				addAttributeOverride((Property) namedElement, stereotype,
						prefix);
			}
		}
	}

	private void addAttributeOverride(Property embedded,
			EObject stereotypeApplication, String prefix) {
		DynamicEObjectImpl override = createChild(stereotypeApplication);
		addChild(stereotypeApplication, override, "value");
		setAttribute(override, "name", embedded.getName());

		DynamicEObjectImpl column = createChild(override);
		setAttribute(override, "column", column);
		setAttribute(column, "name", prefix + "_"
				+ NameUtil.getAbbreviation(embedded));
		if ("String".equals(embedded.getType().getName())) {
			setAttribute(column, "length", 255);
		}
	}

	private class CleanupEnumerationsAction extends BaseUtilityAction {
		private static final String LABEL = "Add Tables and Columns";

		public CleanupEnumerationsAction() {
			super(LABEL);
		}
	}
}
